/*
 * @Author: EyeSklear 1814580085@qq.com
 * @Date: 2024-04-29 16:31:45
 * @LastEditors: EyeSklear 1814580085@qq.com
 * @LastEditTime: 2024-07-25 09:39:05
 * @FilePath: \Scene_Back\src\file-list\file-list.controller.ts
 * @Description:
 *
 * Copyright (c) 2024 by EyeSklear , All Rights Reserved.
 */
/*
 * @Author: EyeSklear 1814580085@qq.com
 * @Date: 2024-02-24 09:18:19
 * @LastEditors: EyeSklear 1814580085@qq.com
 * @LastEditTime: 2024-05-15 21:00:40
 * @LastEditors: EyeSklear 1814580085@qq.com
 * @LastEditTime: 2024-02-27 16:06:27
 * @FilePath: \Scene_Back\src\file-list\file-list.controller.ts
 * @Description:
 *
 * Copyright (c) 2024 by EyeSklear , All Rights Reserved.
 */
import {
  Controller,
  Get,
  Res,
  Post,
  Body,
  Req,
  Patch,
  Param,
  Delete,
  UseInterceptors,
  UploadedFile,
  UploadedFiles,
} from '@nestjs/common';
import * as fse from 'fs-extra';
import { FileListService } from './file-list.service';
import { CreateFileListDto, textFileDto } from './dto/create-file-list.dto';
import { UpdateFileListDto } from './dto/update-file-list.dto';
import { FileInterceptor, FilesInterceptor } from '@nestjs/platform-express';
import { ConfigService } from '@nestjs/config';
import { Request } from 'express';
import * as path from 'path';
import type { Response } from 'express';
import { Public } from 'src/common/decorator/public.decorator';
import {
  CreateGroupToFilelistDto,
  RawGroupToFilelistDto,
} from './dto/create-grouptofilelist.dto';
import * as fs from 'fs';
import axios from 'axios';

@Controller('file-list')
export class FileListController {
  // private readonly fileEnvPath: string;
  constructor(
    private readonly fileListService: FileListService,
    private readonly configService: ConfigService,
  ) {
    // this.fileEnvPath = this.configService.get<string>('FILE_PATH');
  }

  @Post('createFileItem')
  @UseInterceptors(FileInterceptor('file'))
  create(
    @Body() createFileListDto: CreateFileListDto,
    @UploadedFile() file,
    @Req() request: Request,
  ) {
    const user = request.user;
    createFileListDto.uploader = (user as any).email;
    return this.fileListService.create(createFileListDto, file);
  }

  // 分片上传
  @Post('upload')
  @UseInterceptors(FilesInterceptor('chunks'))
  async uploadFiles(
    @UploadedFiles() chunks: Array<Express.Multer.File>,
    @Body() body: any,
    @Req() request: Request,
  ) {
    const { filename, hash, fileHash } = body;
    const dir = path.resolve(
      `${process.env.FILE_PATH}/${(request.user as any).email
      }/temporary/chunkDir_${fileHash}`,
    );

    if (!fs.existsSync(dir)) {
      fs.mkdirSync(dir, { recursive: true });
    }
    const sourcePath = chunks[0].path;
    const targetPath = path.join(dir, hash);
    fs.renameSync(sourcePath, targetPath);
  }
  // 合并分片 并 添加到数据库
  @Post('merge')
  merge(@Body() body, @Req() request: Request) {
    const {
      formName,
      filename,
      hash,
      fileType,
      fileSize,
      role,
      groupuuid,
      folder_id,
    } = body;
    const extractExt = (filename) =>
      filename.slice(filename.lastIndexOf('.'), filename.length);
    const ext = extractExt(filename);
    try {
      //文件操作 读取切片
      let len = 0;
      const bufferList = fs
        .readdirSync(
          path.resolve(
            `${process.env.FILE_PATH}/${(request.user as any).email
            }/temporary/chunkDir_${hash}`,
          ),
        )
        .map((item, index) => {
          const buffer = fs.readFileSync(
            path.resolve(
              `${process.env.FILE_PATH}/${(request.user as any).email
              }/temporary/chunkDir_${hash}/${hash}-${index}`,
            ),
          );
          len += buffer.length;
          return buffer;
        });
      //合并文件
      const buffer = Buffer.concat(bufferList, len);
      const dir = path.resolve(
        `${process.env.FILE_PATH}/${(request.user as any).email}/temporary/`,
      );

      if (!fs.existsSync(dir)) {
        fs.mkdirSync(dir, { recursive: true });
      }

      let folder = 'other'; // 默认文件夹名
      if (fileType.startsWith('image/')) {
        if (fileType === 'image/tiff') {
          folder = 'imageraster';
        } else {
          folder = 'images';
        }
      } else if (fileType.startsWith('audio/')) {
        folder = 'audios';
      } else if (fileType.startsWith('video/')) {
        folder = 'videos';
      } else if (fileType.startsWith('text/')) {
        folder = 'text';
      } else if (fileType.startsWith('application/')) {
        folder = 'application';
      }
      const dateName = new Date().getTime();
      const userDir = path.resolve(
        `${process.env.FILE_PATH}/${(request.user as any).email}/${folder}`,
      );
      if (!fs.existsSync(userDir)) {
        fs.mkdirSync(userDir, { recursive: true });
      }
      const ws = fs.createWriteStream(
        path.resolve(
          `${process.env.FILE_PATH}/${(request.user as any).email
          }/${folder}/${dateName}${ext}`,
        ),
      );
      ws.write(buffer);
      ws.close();
      // 删除分片文件夹
      fse.removeSync(
        path.resolve(
          `${process.env.FILE_PATH}/${(request.user as any).email
          }/temporary/chunkDir_${hash}`,
        ),
      );

      // 存入数据库
      const createFileListDto = new CreateFileListDto();
      createFileListDto.file_name = formName;
      createFileListDto.original_name = filename;
      createFileListDto.src = `${dateName}${ext}`;
      createFileListDto.folder_id = folder_id;
      createFileListDto.raw_type = fileType;
      createFileListDto.size = fileSize;
      createFileListDto.uploader = (request.user as any).email;
      createFileListDto.role = role;
      if (role === 'person') {
        return this.fileListService.mergeFile(createFileListDto);
      } else {
        return this.fileListService.mergeGroupFile(
          createFileListDto,
          groupuuid,
        );
      }
    } catch (error) {
      console.error(error);
    }
  }

  @Get('getUploaded/:hash')
  async getUploaded(@Param('hash') hash: string, @Req() request: Request) {
    const dir = path.resolve(
      `${process.env.FILE_PATH}/${(request.user as any).email
      }/temporary/chunkDir_${hash}`,
    );

    try {
      if (fs.existsSync(dir)) return fs.readdirSync(dir).length;
      else return 0;
    } catch (error) {
      console.error(error);
      return null;
    }
  }

  @Public()
  @Get('getFileAvatar/:id')
  async getFileAvatar(
    @Param('id') id: string,
    @Res() res: Response,
  ): Promise<void> {
    const fileItem = await this.fileListService.findOne(id);
    let filePath = '';
    let folder = 'other'; // 默认文件夹名
    const contentType = 'image/png'; // 默认 Content-Type
    if (fileItem) {
      if (fileItem.raw_type.startsWith('image/')) {
        if (fileItem.raw_type === 'image/tiff') {
          filePath = path.resolve(process.env.FILE_PATH + '/image/tif.png');
        } else {
          folder = 'images';
        }
      } else if (fileItem.raw_type.startsWith('audio/')) {
        filePath = path.resolve(process.env.FILE_PATH + '/image/mp3.png');
      } else if (fileItem.raw_type === 'text/plain') {
        filePath = path.resolve(process.env.FILE_PATH + '/image/txt.png');
      } else if (fileItem.raw_type.startsWith('video/')) {
        filePath = path.resolve(process.env.FILE_PATH + '/image/mp4.png');
      } else if (fileItem.raw_type === 'application/json') {
        filePath = path.resolve(process.env.FILE_PATH + '/image/json.png');
      } else {
        filePath = path.resolve(process.env.FILE_PATH + '/image/file64.png');
      }
      if (!filePath) {
        filePath = path.resolve(
          `${process.env.FILE_PATH}/${fileItem.uploader}/${folder}/${fileItem.src}`,
        );
      }
      res.setHeader('Content-Type', contentType);
      res.set('Cache-Control', 'public, max-age=3600'); // 缓存1小时
      res.set('Last-Modified', new Date().toUTCString());

      const fileStream = fs.createReadStream(filePath);
      fileStream.pipe(res);
    }
  }
  @Get()
  findAll() {
    return this.fileListService.findAll();
  }

  @Get('getFileItemById/:id')
  getFileItemById(@Param('id') id: string) {
    return this.fileListService.findOne(id);
  }

  @Get('getAllFileItemByUser')
  getAllFileItemByUser(@Req() request: Request) {
    const user = request.user;
    const email = (user as any).email;
    return this.fileListService.getAllFileItemByUser(email);
  }

  @Get('getFileItemUserByFolderuuid/:folderuuid')
  getFileItemUserByFolderuuid(
    @Param('folderuuid') folderuuid: string,
    @Req() request: Request,
  ) {
    return this.fileListService.getFileItemUserByFolderuuid(
      folderuuid,
      (request as any).user.email,
    );
  }

  @Patch(':id')
  update(
    @Param('id') id: string,
    @Body() updateFileListDto: UpdateFileListDto,
  ) {
    return this.fileListService.update(id, updateFileListDto);
  }

  @Delete('deleteFileItem/:id')
  remove(@Param('id') id: string) {
    return this.fileListService.remove(id);
  }

  @Get('downloadFileItem/:id')
  downloadFileItem(@Param('id') id: string, @Res() response: Response) {
    return this.fileListService.downloadFileItem(id, response);
  }

  @Public()
  @Get('downloadFileItemStream/:id')
  downloadFileItemStream(@Param('id') id: string, @Res() response: Response) {
    return this.fileListService.downloadFileItemStream(id, response);
  }

  @Public()
  @Get('getFileItemContent/:id')
  getFileItemContent(@Param('id') id: string, @Res() response: Response) {
    return this.fileListService.getFileItemContent(id, response);
  }

  @Get('getChildFileByFolderuuid/:folderuuid')
  getChildFileByFolderuuid(@Param('folderuuid') folderuuid: string) {
    return this.fileListService.getChildFileByFolderuuid(folderuuid)
  }

  @Post('savePlotResult')
  savePlotResult(@Body() body: any, @Req() request: Request) {
    return this.fileListService.savePlotResult(body, (request.user as any).email)
  }

  // set 小组和文件列表之间的关系
  @Post('createFileItemToGroup/:groupuuid')
  @UseInterceptors(FileInterceptor('file'))
  createFileItemToGroup(
    @Body() createFileListDto: CreateFileListDto,
    @UploadedFile() file,
    @Req() request: Request,
    @Param('groupuuid') groupuuid: string,
  ) {
    const user = request.user;
    createFileListDto.uploader = (user as any).email;
    return this.fileListService.createFileItemToGroup(
      createFileListDto,
      file,
      groupuuid,
    );
  }

  @Post('moveFileItemToGroup')
  moveFileItemToGroup(
    @Body() createGroupToFilelistDto: CreateGroupToFilelistDto,
    @Req() request: Request,
  ) {
    createGroupToFilelistDto.belong = (request.user as any).email;
    return this.fileListService.moveFileItemToGroup(createGroupToFilelistDto);
  }

  @Get('copyFileItemToUser/:fileuuid/:folderuuid')
  copyFileItemToUser(
    @Param('fileuuid') fileuuid: string,
    @Param('folderuuid') folderuuid: string,
    @Req() request: Request,
  ) {
    return this.fileListService.copyFileItemToUser(fileuuid, folderuuid, (request.user as any).email)
  }

  @Post('copyFileItemToGroup')
  copyFileItemToGroup(
    @Body() params: {
      fileuuid: string;
      folderuuid: string;
      groupuuid: string;
    },
    @Req() request: Request,
  ) {
    return this.fileListService.copyFileItemToGroup(params.fileuuid, params.folderuuid, params.groupuuid, (request.user as any).email)
  }

  @Get('getFileItemByGroupuuidFolderuuid/:groupuuid/:folderuuid')
  getFileItemByGroupuuidFolderuuid(@Param('groupuuid') groupuuid: string, @Param('folderuuid') folderuuid: string) {
    return this.fileListService.getFileItemByGroupuuidFolderuuid(groupuuid, folderuuid);
  }

  @Delete('deleteFileItemFromGroup/:fileuuid')
  deleteFileItemFromGroup(@Param('fileuuid') fileuuid: string) {
    return this.fileListService.deleteFileItemFromGroup(fileuuid);
  }

  //获得图片文件列表接口

  @Get('getPicFileItemByUserInPerson/:folderuuid')
  getPicFileItemByUserInPerson(@Param('folderuuid') folderuuid: string, @Req() request: Request) {
    const email = (request.user as any).email;
    return this.fileListService.getPicFileItemByUserInPerson(folderuuid, email);
  }

  @Get('getPicFileItemByUserInGroup/:groupuuid/:folderuuid')

  getPicFileItemByUserInGroup(@Param('groupuuid') groupuuid: string, @Param('folderuuid') folderuuid: string, @Req() request: Request) {
    const email = (request.user as any).email;
    return this.fileListService.getPicFileItemByUserInGroup(groupuuid, folderuuid, email);
  }

  @Get('getAllPicFileItemByUserInPerson')
  getAllPicFileItemByUserInPerson(@Req() request: Request) {
    const email = (request.user as any).email;
    return this.fileListService.getAllPicFileItemByUserInPerson(email);
  }

  @Get('getAllPicFileItemByUserInGroup/:groupuuid')
  getAllPicFileItemByUserInGroup(@Param('groupuuid') groupuuid: string, @Req() request: Request) {
    const email = (request.user as any).email;
    return this.fileListService.getAllPicFileItemByUserInGroup(groupuuid, email);
  }

  //获得视频文件列表接口
  @Get('getVidFileItemByUserInPerson/:folderuuid')
  getVidFileItemByUserInPerson(@Param('folderuuid') folderuuid: string, @Req() request: Request) {
    const email = (request.user as any).email;
    return this.fileListService.getVidFileItemByUserInPerson(folderuuid, email);
  }

  @Get('getVidFileItemByUserInGroup/:groupuuid/:folderuuid')
  getVidFileItemByUserInGroup(@Param('groupuuid') groupuuid: string, @Param('folderuuid') folderuuid: string, @Req() request: Request) {
    const email = (request.user as any).email;
    return this.fileListService.getVidFileItemByUserInGroup(groupuuid, folderuuid, email);
  }

  //获得音频文件列表接口
  @Get('getAudFileItemByUserInPerson/:folderuuid')
  getAudFileItemByUserInPerson(@Param('folderuuid') folderuuid: string, @Req() request: Request) {
    const email = (request.user as any).email;
    return this.fileListService.getAudFileItemByUserInPerson(folderuuid, email);
  }

  @Get('getAudFileItemByUserInGroup/:groupuuid/:folderuuid')
  getAudFileItemByUserInGroup(@Param('groupuuid') groupuuid: string, @Param('folderuuid') folderuuid: string, @Req() request: Request) {
    const email = (request.user as any).email;
    return this.fileListService.getAudFileItemByUserInGroup(groupuuid, folderuuid, email);
  }

  //获得文本文件列表接口
  @Get('getTxtFileItemByUserInPerson')
  getTxtFileItemByUserInPerson(@Req() request: Request) {
    const email = (request.user as any).email;
    return this.fileListService.getTxtFileItemByUserInPerson(email);
  }

  @Post('generateTxtFile')
  generateTxtFile(@Req() request: Request, @Body() body: textFileDto) {
    const email = (request.user as any).email;
    try {
      const src = `${new Date().getTime() + '.txt'}`;
      const filePath = path.resolve(
        `${process.env.FILE_PATH}/${email}/text/${src}`,
      );
      if (fs.existsSync(filePath)) {
        return '文件已经存在，有重名错误';
      }
      fs.writeFileSync(filePath, body.file_content);
      const createFileListDto = new CreateFileListDto();
      createFileListDto.file_name = body.file_name;
      createFileListDto.raw_type = 'text/plain';
      createFileListDto.src = body.file_name;
      createFileListDto.original_name = body.file_name;
      createFileListDto.uploader = email;
      createFileListDto.src = src;
      fs.stat(filePath, (err, stats) => {
        createFileListDto.size = String(stats.size);
        return this.fileListService.createSingleRecord(createFileListDto);
      });
    } catch (error) {
      console.error('生成文件失败:', error);
      return '生成文件失败';
    }
  }

  @Get('getTxtFileItemByUserInGroup')
  getTxtFileItemByUserInGroup(@Req() request: Request) {
    const email = (request.user as any).email;
    return this.fileListService.getTxtFileItemByUserInGroup(email);
  }

  //获得矢量文件列表接口
  @Get('getJsonFileItemByUserInPerson/:folderuuid')
  getJsonFileItemByUserInPerson(@Param('folderuuid') folderuuid: string, @Req() request: Request) {
    const email = (request.user as any).email;
    return this.fileListService.getJsonFileItemByUserInPerson(folderuuid, email);
  }

  @Get('getJsonFileItemByUserInGroup/:groupuuid/:folderuuid')
  getJsonFileItemByUserInGroup(@Param('groupuuid') groupuuid: string, @Param('folderuuid') folderuuid: string, @Req() request: Request) {
    const email = (request.user as any).email;
    return this.fileListService.getJsonFileItemByUserInGroup(groupuuid, folderuuid, email);
  }

  //获得栅格文件列表接口
  @Get('getRasterFileItemByUserInPerson/:folderuuid')
  getRasterFileItemByUserInPerson(@Param('folderuuid') folderuuid: string, @Req() request: Request) {
    const email = (request.user as any).email;
    return this.fileListService.getRasterFileItemByUserInPerson(folderuuid, email);
  }

  @Get('getRasterFileItemByUserInGroup/:groupuuid/:folderuuid')
  getRasterFileItemByUserInGroup(@Param('groupuuid') groupuuid: string, @Param('folderuuid') folderuuid: string, @Req() request: Request) {
    const email = (request.user as any).email;
    return this.fileListService.getRasterFileItemByUserInGroup(groupuuid, folderuuid, email);
  }

  // 利用 Chatts 文本转语音并保存
  @Post('textToAuidoByChattts')
  async textToAuidoByChattts(@Body() param: any, @Req() request: Request) {
    const dateName = new Date().getTime();
    // const dir = `${process.env.FILE_PATH}/${(request.user as any).email}/audios/${dateName}.wav`
    const formData = new FormData();
    formData.append('text', param.content);
    formData.append('voice', param.seed.toString());
    formData.append('prompt', param.prompt.toString());
    formData.append('temperature', param.temperate.toString());
    formData.append('top_p', param.top_p.toString());
    formData.append('top_k', param.top_k.toString());
    formData.append('skip_refine', param.isRefineText ? '1' : ' 0');
    formData.append('is_split', param.isNumToText ? '0' : '1');
    formData.append('filename', `${dateName}.wav`);
    formData.append(
      'targetDIR',
      `${process.env.FILE_PATH}/${(request.user as any).email}/audios`,
    );
    //Chatts 转换
    const charttsRes = await axios.post(
      `${process.env.VITE_CHATTTS_URL}/chattsForScence`,
      formData,
    );
    // 成功后存入数据库
    const createFileListDto = new CreateFileListDto();
    createFileListDto.file_name = `Chatts${param.content.slice(0, 4)}${dateName
      .toString()
      .slice(0, 4)}`;
    createFileListDto.original_name = `${param.content.slice(0, 4)}`;
    createFileListDto.src = `${dateName}.wav`;
    createFileListDto.folder_id = '-1';
    createFileListDto.raw_type = 'audio/mpeg';
    createFileListDto.size = charttsRes.data.audio_files[0].file_size;
    createFileListDto.uploader = (request.user as any).email;
    createFileListDto.role = param.role;
    if (param.role === 'person') {
      return this.fileListService.createSingleDBRecord(createFileListDto);
    } else {
      return this.fileListService.createGroupSingleDBRecord(
        createFileListDto,
        param.groupuuid,
      );
    }
  }
}
